import pytest
import requests
import json
from unittest.mock import patch, MagicMock
import time
import random

# 配置信息
API_URL = "https://cvm.tencentcloudapi.com/"
REGION = "ap-guangzhou"
SECRET_ID = "your-secret-id"
SECRET_KEY = "your-secret-key"


def generate_signature(params, secret_key):
    """生成签名（模拟实现）"""
    return "mock-signature"


def send_request(action, params=None):
    """发送API请求（模拟实现）"""
    if params is None:
        params = {}
    common_params = {
        "Action": action,
        "Version": "2017-03-12",
        "Region": REGION,
        "SecretId": SECRET_ID,
        "Timestamp": int(time.time()),
        "Nonce": random.randint(1, 1000000),
        "SignatureMethod": "HmacSHA256"
    }
    all_params = {**common_params, **params}
    all_params["Signature"] = generate_signature(all_params, SECRET_KEY)

    response = requests.post(API_URL, data=all_params)
    return response.json()


class TestDescribeRegions:
    @patch('requests.post')
    def test_describe_regions_success(self, mock_post):
        """测试成功查询地域列表"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "RegionSet": [
                    {
                        "Region": "ap-guangzhou",
                        "RegionName": "广州",
                        "RegionState": "AVAILABLE"
                    },
                    {
                        "Region": "ap-shanghai",
                        "RegionName": "上海",
                        "RegionState": "AVAILABLE"
                    }
                ],
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("DescribeRegions")

        assert "Response" in result
        assert "RegionSet" in result["Response"]
        assert len(result["Response"]["RegionSet"]) > 0

    @patch('requests.post')
    def test_internal_error(self, mock_post):
        """测试内部错误"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "InternalError",
                    "Message": "操作内部错误"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("DescribeRegions")
        assert result["Response"]["Error"]["Code"] == "InternalError"

    @patch('requests.post')
    def test_invalid_action(self, mock_post):
        """测试无效操作名"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "InvalidAction",
                    "Message": "操作名不存在"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("InvalidAction")
        assert result["Response"]["Error"]["Code"] == "InvalidAction"

    @patch('requests.post')
    def test_invalid_parameter(self, mock_post):
        """测试无效参数"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "InvalidParameter",
                    "Message": "参数错误"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("DescribeRegions", {"InvalidParam": "invalid"})
        assert result["Response"]["Error"]["Code"] == "InvalidParameter"

    @patch('requests.post')
    def test_invalid_parameter_value(self, mock_post):
        """测试参数取值错误"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "InvalidParameterValue",
                    "Message": "参数取值错误"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("DescribeRegions", {"InvalidParam": "invalid"})
        assert result["Response"]["Error"]["Code"] == "InvalidParameterValue"

    @patch('requests.post')
    def test_missing_parameter(self, mock_post):
        """测试缺少必要参数"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "MissingParameter",
                    "Message": "缺少参数错误"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        # 虽然DescribeRegions不需要必选参数，但可以模拟其他接口的情况
        result = send_request("DescribeRegions", {"RequiredParam": None})
        assert result["Response"]["Error"]["Code"] == "MissingParameter"

    @patch('requests.post')
    def test_no_permission(self, mock_post):
        """测试无权限操作"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "UnauthorizedOperation",
                    "Message": "无权限操作"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("DescribeRegions")
        assert result["Response"]["Error"]["Code"] == "UnauthorizedOperation"

    @patch('requests.post')
    def test_unregistered_action(self, mock_post):
        """测试未注册操作"""
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "Response": {
                "Error": {
                    "Code": "UnregisteredAction",
                    "Message": "未注册的操作"
                },
                "RequestId": "1234567890"
            }
        }
        mock_post.return_value = mock_response

        result = send_request("UnregisteredAction")
        assert result["Response"]["Error"]["Code"] == "UnregisteredAction"


# 启动测试函数
def run_tests():
    pytest.main([__file__, "-v", "-s"])


if __name__ == "__main__":
    run_tests()